﻿#pragma once


#include <QDialog>
#include <QPushButton>
#include "QListView"
#include "QStringListModel"
#include "QFileDialog"
#include "QMessageBox"
#include "QApplication"
#include "QVBoxLayout"
#include <QDesktopWidget>
#include <QLibrary>
#include <QApplication>
#include <QLabel>
#include <QComboBox>
#include "QListView"
#include "QStringListModel"
#include "QLineEdit"
#include "QSpinBox"
#include "QRadioButton"
#include <QSettings>

#include "commonfunction.h"

#include "halcon_opencv.h"

using namespace std;

#include "qt_graphics_view_image.h"
#include "qt_graphics_shape_rectangle.h"

class DetectionCharacter :public QDialog
{
public:
    //json m_json_data;
    QSettings* m_qsettings;
    Mat m_image ,m_image_show;
    QString m_section   = "";

    MyQGraphicsView* m_view ;

    QPushButton* m_pushbutton_load_image;

    QPushButton* m_pushbutton_open_model_image;

    QPushButton* m_pushbutton_save_model_image;

    QLabel* m_qlabel_count;
    QSpinBox* m_qspinbox_count;

    QLabel* m_qlabel_distance;
    QSpinBox* m_qspinbox_distance;

    QLabel * m_qlabel_threshold_low;
    QSpinBox * m_qspinbox_threshold_low;

    QLabel * m_qlabel_threshold_high;
    QSpinBox * m_qspinbox_threshold_high;
   

    QLabel * m_qlabel_less_standard;
    QSpinBox * m_qspinbox_less_standard;
    
    QLabel * m_qlabel_more_standard;
    QSpinBox * m_qspinbox_more_standard;


    int row1, column1, row2, column2;


    

    QPushButton* m_pushbutton_create_model;

    QPushButton* m_pushbutton_detection;
    QPushButton* m_pushbutton_save_parameter;
    QPushButton* m_pushbutton_return;

    QLabel* m_qlabel_message;

    HObject image_in;
    int m_result;

    QString m_model_dir;
    HDevProcedure* m_proc_createModel;
    HDevProcedureCall* m_call_createModel;
    HObject skeleton;
    HObject skeleton_dilation;
    HTuple model_match, model_match_row, model_match_column, model_match_angle, models_row1, models_column1, models_row2, models_column2;


    HDevProcedure* m_proc_detection;
    HDevProcedureCall* m_call_detection;
    HObject  region_show,region_error;

    double m_model_row, m_model_column, m_model_phi, m_model_length1, m_model_length2;

public:
    explicit DetectionCharacter::DetectionCharacter(QDialog* parent, QSettings* qsettings, QString section) : QDialog(parent)
    {
        m_qsettings = qsettings;
        m_section = section;

        this->setWindowTitle(("字符检测"));
        QRect desktop_rect = QApplication::desktop()->geometry();
        double ratio_x = desktop_rect.width() / 1920.0;
        double ratio_y = desktop_rect.height() / 1080.0;

        move(0, 0);
        setFixedSize(1920 * ratio_x, 1010 * ratio_y);

        m_view = new MyQGraphicsView(this);
        m_view->setGeometry(660 * ratio_x, 0, 1000 * 1.25 * ratio_x, 800 * 1.25 * ratio_y);



        m_view->m_graphics_shape_rect = new GraphicsShapeRect(100, 100, 100, 100);
        m_view->m_scene->addItem(m_view->m_graphics_shape_rect);
        QRectF qrectf = m_view->m_graphics_shape_rect->boundingRect();
        row1 = (int)qrectf.y();
        column1 = (int)qrectf.x();
        row2 = (int)(qrectf.y() + qrectf.height());
        column2 = (int)(qrectf.x() + qrectf.width());

        connect(m_view->m_graphics_shape_rect, &GraphicsShapeRect::sendMessage, m_view->m_pixmapItem, &MyQGraphicsPixmapItem::receiveMessage);

        QSize control_size(150 * ratio_x, 40 * ratio_y);

        QWidget* p = new QWidget(this);
        p->move(0 * ratio_x, 0 * ratio_y);
        p->setFixedSize(600 * ratio_x, 800 * ratio_y);

        QGridLayout* qgridLayout = new QGridLayout();
        p->setLayout(qgridLayout);

        int index = 0;

        QSize ButtonSize(120 * ratio_x, 40 * ratio_y);



        m_qlabel_count = new QLabel();
        m_qlabel_count->setText("字符数量");
        m_qlabel_count->setFixedSize(control_size);
        qgridLayout->addWidget(m_qlabel_count, index, 0);


        m_qspinbox_count = new QSpinBox();
        m_qspinbox_count->setFixedSize(control_size);
        m_qspinbox_count->setMinimum(0);
        m_qspinbox_count->setMaximum(10);
        qgridLayout->addWidget(m_qspinbox_count, index, 1);

        index++;

        m_qlabel_distance = new QLabel();
        m_qlabel_distance->setText("骨架位置判断阈值");
        m_qlabel_distance->setFixedSize(control_size);
        qgridLayout->addWidget(m_qlabel_distance, index, 0);


        m_qspinbox_distance = new QSpinBox();
        m_qspinbox_distance->setFixedSize(control_size);
        m_qspinbox_distance->setMinimum(4);
        m_qspinbox_distance->setMaximum(20);
        qgridLayout->addWidget(m_qspinbox_distance, index, 1);
        index++;


        m_qlabel_threshold_low = new QLabel();
        m_qlabel_threshold_low->setText("灰度阈值下限");
        m_qlabel_threshold_low->setFixedSize(control_size);
        qgridLayout->addWidget(m_qlabel_threshold_low, index, 0);


        m_qspinbox_threshold_low = new QSpinBox();
        m_qspinbox_threshold_low->setFixedSize(control_size);
        m_qspinbox_threshold_low->setMinimum(0);
        m_qspinbox_threshold_low->setMaximum(255);
        qgridLayout->addWidget(m_qspinbox_threshold_low, index, 1);

        index++;

        m_qlabel_threshold_high = new QLabel();
        m_qlabel_threshold_high->setText("灰度阈值上限");
        m_qlabel_threshold_high->setFixedSize(control_size);
        qgridLayout->addWidget(m_qlabel_threshold_high, index, 0);


        m_qspinbox_threshold_high = new QSpinBox();
        m_qspinbox_threshold_high->setFixedSize(control_size);
        m_qspinbox_threshold_high->setMinimum(0);
        m_qspinbox_threshold_high->setMaximum(255);
        qgridLayout->addWidget(m_qspinbox_threshold_high, index, 1);

        index++;

        m_qlabel_less_standard = new QLabel();
        m_qlabel_less_standard->setText("字符缺失标准");
        m_qlabel_less_standard->setFixedSize(control_size);
        qgridLayout->addWidget(m_qlabel_less_standard, index, 0);

        m_qspinbox_less_standard = new QSpinBox();
        m_qspinbox_less_standard->setFixedSize(control_size);
        m_qspinbox_less_standard->setMinimum(3);
        m_qspinbox_less_standard->setMaximum(100000);
        qgridLayout->addWidget(m_qspinbox_less_standard, index, 1);

        index++;

        m_qlabel_more_standard = new QLabel();
        m_qlabel_more_standard->setText("字符溢出标准");
        m_qlabel_more_standard->setFixedSize(control_size);
        qgridLayout->addWidget(m_qlabel_more_standard, index, 0);


        m_qspinbox_more_standard = new QSpinBox();
        m_qspinbox_more_standard->setFixedSize(control_size);
        m_qspinbox_more_standard->setMinimum(3);
        m_qspinbox_more_standard->setMaximum(100000);
        qgridLayout->addWidget(m_qspinbox_more_standard, index, 1);

        index++;

        m_pushbutton_save_parameter = new QPushButton(this);
        m_pushbutton_save_parameter->setFixedSize(control_size);
        m_pushbutton_save_parameter->setText("保存参数");
        connect(m_pushbutton_save_parameter, &QPushButton::clicked, this, &DetectionCharacter::saveParameter);
        qgridLayout->addWidget(m_pushbutton_save_parameter, index, 0);

        m_pushbutton_create_model = new QPushButton(this);
        m_pushbutton_create_model->setFixedSize(control_size);
        m_pushbutton_create_model->setText("创建模型");
        connect(m_pushbutton_create_model, &QPushButton::clicked, this, &DetectionCharacter::create_model);
        qgridLayout->addWidget(m_pushbutton_create_model, index, 1);

        index++;
        m_pushbutton_detection = new QPushButton(this);
        m_pushbutton_detection->setFixedSize(control_size);
        m_pushbutton_detection->setText("检测");
        connect(m_pushbutton_detection, &QPushButton::clicked, this, &DetectionCharacter::detectionImage);
        qgridLayout->addWidget(m_pushbutton_detection, index, 0);

        index++;
        m_pushbutton_return = new QPushButton(this);
        m_pushbutton_return->setFixedSize(control_size);
        m_pushbutton_return->setText("退出");
        qgridLayout->addWidget(m_pushbutton_return, index, 0);
        connect(m_pushbutton_return, &QPushButton::clicked, this, [=]() {
            this->hide();
            });


        try
        {


            m_proc_createModel = new HDevProcedure("createCharacterModel");
            m_call_createModel = new HDevProcedureCall(*m_proc_createModel);

            m_proc_detection = new HDevProcedure("detectionCharacter");
            m_call_detection = new HDevProcedureCall(*m_proc_detection);
        }
        catch (HDevEngineException& hdev_exception)
        {
            //QMessageBox::information(nullptr, "", hdev_exception.Message());
        }


        loadParameter();
    }
    void create_model()
    {
        QString message;

        if (m_image.empty())
        {
            message += "创建字符检测模板失败，模板图像为空 ";
            ////QMessageBox::information(nullptr, m_model_image_path, message);
            return;
        }
        m_image_show = m_image.clone();
        try
        {
            HObject image = matToHImage(m_image_show);

            // Set the input parameters of the procedure
            m_call_createModel->SetInputIconicParamObject(1, image);
            m_call_createModel->SetInputCtrlParamTuple("row1", row1);
            m_call_createModel->SetInputCtrlParamTuple("column1", column1);
            m_call_createModel->SetInputCtrlParamTuple("row2", row2);
            m_call_createModel->SetInputCtrlParamTuple("column2", column2);
            m_call_createModel->SetInputCtrlParamTuple("threshold_low", m_qspinbox_threshold_low->value());
            m_call_createModel->SetInputCtrlParamTuple("threshold_high", m_qspinbox_threshold_high->value());
            m_call_createModel->SetInputCtrlParamTuple("count", m_qspinbox_count->value());
            m_call_createModel->SetInputCtrlParamTuple("distance", m_qspinbox_distance->value());

            // Execute the procedure

            //HDevEngine().StartDebugServer();
            //m_call_createModel->SetWaitForDebugConnection(true);
            m_call_createModel->Execute();
            //HDevEngine().StopDebugServer();



            // get the output parameters
            HTuple ret = m_call_createModel->GetOutputCtrlParamTuple(1);
            HTuple message = m_call_createModel->GetOutputCtrlParamTuple(2);
            model_match = m_call_createModel->GetOutputCtrlParamTuple(3);
            model_match_row = m_call_createModel->GetOutputCtrlParamTuple(4);
            model_match_column = m_call_createModel->GetOutputCtrlParamTuple(5);
            model_match_angle = m_call_createModel->GetOutputCtrlParamTuple(6);
            models_row1 = m_call_createModel->GetOutputCtrlParamTuple(7);
            models_column1 = m_call_createModel->GetOutputCtrlParamTuple(8);
            models_row2 = m_call_createModel->GetOutputCtrlParamTuple(9);
            models_column2 = m_call_createModel->GetOutputCtrlParamTuple(10);


            m_result = ret[0].I();
            if (m_result == 1)
            {
                message += "创建字符OK ";
                skeleton = m_call_createModel->GetOutputIconicParamObject("skeleton");
                skeleton_dilation = m_call_createModel->GetOutputIconicParamObject("skeleton_dilation");

                m_image_show = drawRegion(m_image_show, skeleton, Scalar(0, 255, 0));
                m_image_show = drawRegion(m_image_show, skeleton_dilation, Scalar(0, 255, 0));
            }
            else
            {
                message += "NG ";
                //QMessageBox::information(nullptr, "", "创建字符检测模板失败");
            }





            QImage q_image = matToQImage(m_image_show);
            m_view->setImage(q_image, "");
            m_view->setRectPose(row1, column1, row2, column2);
            return;
        }
        catch (HDevEngineException& hdev_exception)
        {
            HDevEngine().SetHDevOperatorImpl(NULL);

            //QMessageBox::information(nullptr, "", hdev_exception.Message());
        }


        return;
    }
    virtual void DetectionCharacter::detectionImage()
    {
        Mat image_show = himageToMat(image_in);
        if (image_show.empty())
        {
            //QMessageBox::information(nullptr, "", "没有图像");
            return;
        }
        QString message;
        //HObject image = matToHImage(m_image);
        detection(image_in, message);


        draw(image_show, image_show);

        QImage q_image = matToQImage(image_show);
        m_view->setImage(q_image, message);

    }
    virtual bool DetectionCharacter::detection(HObject image_in, QString& message)
    {
        if (m_image.empty())
        {
            message += "检测图像为空 ";
            return false;
        }
        try
        {
            //HObject image = matToHImage(image_in);

            // Set the input parameters of the procedure
            m_call_detection->SetInputIconicParamObject("image", image_in);

            m_call_detection->SetInputIconicParamObject("skeleton", skeleton);
            m_call_detection->SetInputIconicParamObject("skeleton_dilation", skeleton_dilation);

            m_call_detection->SetInputCtrlParamTuple("row1", row1);
            m_call_detection->SetInputCtrlParamTuple("column1", column1);
            m_call_detection->SetInputCtrlParamTuple("row2", row2);
            m_call_detection->SetInputCtrlParamTuple("column2", column2);
            m_call_detection->SetInputCtrlParamTuple("threshold_low", m_qspinbox_threshold_low->value());
            m_call_detection->SetInputCtrlParamTuple("threshold_high", m_qspinbox_threshold_high->value());
            m_call_detection->SetInputCtrlParamTuple("distance", m_qspinbox_distance->value());

            m_call_detection->SetInputCtrlParamTuple("model_match", model_match);
            m_call_detection->SetInputCtrlParamTuple("model_match_row", model_match_row);
            m_call_detection->SetInputCtrlParamTuple("model_match_column", model_match_column);
            m_call_detection->SetInputCtrlParamTuple("models_row1", models_row1);
            m_call_detection->SetInputCtrlParamTuple("models_column1", models_column1);
            m_call_detection->SetInputCtrlParamTuple("models_row2", models_row2);
            m_call_detection->SetInputCtrlParamTuple("models_column2", models_column2);
            m_call_detection->SetInputCtrlParamTuple("model_match_angle", model_match_angle);
            m_call_detection->SetInputCtrlParamTuple("less_standard", m_qspinbox_less_standard->value());
            m_call_detection->SetInputCtrlParamTuple("more_standard", m_qspinbox_more_standard->value());


            // Execute the procedure

            //HDevEngine().StartDebugServer();
            //m_call_detection->SetWaitForDebugConnection(true);
            m_call_detection->Execute();
            //HDevEngine().StopDebugServer();


            region_error = m_call_detection->GetOutputIconicParamObject("region_error");
            region_show = m_call_detection->GetOutputIconicParamObject("region_show");
            // get the output parameters
            HTuple ret = m_call_detection->GetOutputCtrlParamTuple(1);
            HTuple msg = m_call_detection->GetOutputCtrlParamTuple(2);
            m_result = ret[0].I();
            if (m_result == 1)
            {
                message += msg[0].S();
                return true;
            }
            else
            {
                message += msg[0].S();
                return false;
            }



        }
        catch (HDevEngineException& hdev_exception)
        {
            message = hdev_exception.Message();
            return false;
        }
        return true;
    }
    virtual void DetectionCharacter::draw(Mat image_in, Mat& image_out)
    {
        if (image_in.empty())
            return;

        image_out = drawRegion(image_in.clone(), region_show, Scalar(0, 255, 0));
        image_out = drawRegion(image_out, region_error, Scalar(0, 0, 255));
        GenEmptyRegion(&region_show);
        GenEmptyRegion(&region_error);
    }
    virtual void DetectionCharacter::loadParameter()
    {
        QString section = m_section;
        try
        {
            m_qspinbox_count->setValue(m_qsettings->value(section + "/" + "count",3).toInt());
            m_qspinbox_distance->setValue(m_qsettings->value(section + "/" + "distance",4).toInt());
            m_qspinbox_threshold_low->setValue(m_qsettings->value(section + "/" + "threshold_low").toInt());
            m_qspinbox_threshold_high->setValue(m_qsettings->value(section + "/" + "threshold_high").toInt());
            m_qspinbox_less_standard->setValue(m_qsettings->value(section + "/" + "less_standard").toInt());
            m_qspinbox_more_standard->setValue(m_qsettings->value(section + "/" + "more_standard").toInt());

            row1 = m_qsettings->value(section + "/" + "row1", 100).toInt();
            column1 = m_qsettings->value(section + "/" + "column1", 100).toInt();
            row2 = m_qsettings->value(section + "/" + "row2", 200).toInt();
            column2 = m_qsettings->value(section + "/" + "column2", 200).toInt();

            m_view->setRectPose(row1, column1, row2, column2);
        }
        catch (exception& error)
        {
            QMessageBox::critical(nullptr, error.what(), m_section + "参数需要重新设置");
        }

        return;
    }
    virtual void DetectionCharacter::saveParameter()
    {
        try
        {

            QRectF qrectf = m_view->m_graphics_shape_rect->boundingRect();
            row1 = m_view->m_graphics_shape_rect->pos().y() + (int)qrectf.y();
            column1 = m_view->m_graphics_shape_rect->pos().x() + (int)qrectf.x();
            row2 = m_view->m_graphics_shape_rect->pos().y() + (int)(qrectf.y() + qrectf.height());
            column2 = m_view->m_graphics_shape_rect->pos().x() + (int)(qrectf.x() + qrectf.width());

            m_qsettings->setValue(m_section + "/" + "row1", row1);
            m_qsettings->setValue(m_section + "/" + "column1", column1);
            m_qsettings->setValue(m_section + "/" + "row2", row2);
            m_qsettings->setValue(m_section + "/" + "column2", column2);

            m_qsettings->setValue(m_section + "/" + "count", m_qspinbox_count->value());
            m_qsettings->setValue(m_section + "/" + "distance", m_qspinbox_distance->value());
            m_qsettings->setValue(m_section + "/" + "threshold_low", m_qspinbox_threshold_low->value());
            m_qsettings->setValue(m_section + "/" + "threshold_high", m_qspinbox_threshold_high->value());
            m_qsettings->setValue(m_section + "/" + "less_standard", m_qspinbox_less_standard->value());
            m_qsettings->setValue(m_section + "/" + "more_standard", m_qspinbox_more_standard->value());
        }
        catch (exception& error)
        {
            //QMessageBox::critical(nullptr, error.what(), m_section + "参数需要重新设置");
        }
    }
    virtual bool DetectionCharacter::showDialog()
    {
        return true;
    }
};
#pragma execution_character_set("utf-8")
